package com.mugui.base.net.forward;

import java.lang.annotation.Annotation;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.alibaba.fastjson.JSONArray;
import com.mugui.Mugui;
import com.mugui.base.base.ApplicationContext;
import com.mugui.base.base.Autowired;
import com.mugui.base.base.Component;
import com.mugui.base.client.net.auto.AutoManager;
import com.mugui.base.client.net.base.ManagerInterface;
import com.mugui.base.client.net.base.Module;
import com.mugui.base.client.net.classutil.DataSave;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.XmlUtil;

@AutoManager
@Component
public class ForwardManager implements ManagerInterface<String, Object> {
	private static HashMap<String, Object> map = null;

	public void init() {
		clear();
		map = new HashMap<>();
		applicationContext = DataSave.context;
	}

	public Set<Entry<String, Object>> entrySet() {
		return map.entrySet();
	}

	private ApplicationContext applicationContext = null;

	public boolean init(Object name) {
		init();
		loadByDefaultConfigXml();
		loadByClass((Class<?>) name);
		return true;
	}

	private String url = null;
	private String value = null;
	private String inject = null;
	private String classes = null;

	private void loadByDefaultConfigXml() {
		try {
			ClassPathResource resource = new ClassPathResource("ForwardConfig.xml");
			Document document = null;
			try {
				document = XmlUtil.readXML(resource.getStream());
			} catch (Exception e) {
				return;
			}
			NodeList list = document.getChildNodes().item(0).getChildNodes();
			for (int i = 0; i < list.getLength(); i++) {
				Node item = list.item(i);
				if (item.getNodeName().equals("server-node")) {
					NodeList childNodes = item.getChildNodes();
					for (int j = 0; j < childNodes.getLength(); j++) {
						if (childNodes.item(j).getNodeName().equals("url")) {
							url = childNodes.item(j).getChildNodes().item(0).getNodeValue();
						} else if (childNodes.item(j).getNodeName().equals("value")) {
							value = childNodes.item(j).getChildNodes().item(0).getNodeValue();
						} else if (childNodes.item(j).getNodeName().equals("inject")) {
							inject = childNodes.item(j).getChildNodes().item(0).getNodeValue();
						} else if (childNodes.item(j).getNodeName().equals("classes")) {
							classes = childNodes.item(j).getChildNodes().item(0).getNodeValue();
						}
					}
					System.out.println(url + " " + value + " " + inject + " " + classes);
					Forward forward = new Forward() {
						String u = url;
						String v = value;
						String i = inject;
						String c = classes;

						@Override
						public Class<? extends Annotation> annotationType() {
							// TODO Auto-generated method stub
							return null;
						}

						@Override
						public String[] value() {
							return v.split(",");
						}

						@Override
						public String url() {
							return u;
						}

						@Override
						public String[] inject() {
							return i.split(",");
						}

						@SuppressWarnings("unchecked")
						@Override
						public Class<Mugui>[] classes() {
							if (StringUtils.isBlank(c)) {
								return null;
							}
							String[] split = c.split(",");
							Class<Mugui>[] classes = new Class[split.length];
							try {
								for (int i = 0; i < split.length; i++) {
									Class<?> forName = Class.forName(split[i]);
									Object bean = applicationContext.getBean(forName);
									if (forName.isAnnotationPresent(Module.class) && bean instanceof Mugui) {
										classes[i] = (Class<Mugui>) forName;
										continue;
									}
									throw new RuntimeException("类属性错误，关于 class:" + forName.getName());
								}
							} catch (Exception e) {
								e.printStackTrace();
								throw new RuntimeException("配置文件错误", e);
							}
							return classes;
						}

					};

					if (StringUtils.isNotBlank(forward.url()))
						for (String key : forward.value()) {
							handleKey(key, forward);
						}
					if (inject != null) {
						injectOtherServer(forward);
					}
				}

			}
		} catch (UtilException e) {
			e.printStackTrace();
		}
	}

	@Autowired
	private ForwardTask forwardTask;

	private void injectOtherServer(Forward forward) {
		for (String str : forward.inject()) {
			if (StringUtils.isBlank(str))
				continue;

			ForwardBean forwardBean = new ForwardBean();
			forwardBean.setUrl(forward.url());
			String value = null;
			if (forward.value() != null && forward.value().length > 0)
				value = ArrayUtil.join(forward.value(), ",");
			Class<Mugui>[] classes2 = forward.classes();
			if (classes2 != null && classes2.length > 0) {
				JSONArray object = new JSONArray();
				for (Class<Mugui> class1 : classes2) {
					Module annotation = class1.getAnnotation(Module.class);
					String module = annotation.name() + "." + annotation.type() + ".*";
					if (value == null) {
						value = module;
					} else {
						value += "," + module;
					}
					// 处理webSocket
//					if (class1.isAnnotationPresent(WebSocket.class)) {
//						WebSocket annotation2 = class1.getAnnotation(WebSocket.class);
//						WebSocketBean webSocketBean = new WebSocketBean();
//						webSocketBean.setBlank(annotation2.blank());
//						webSocketBean.setClass_name(class1.getName());
//						webSocketBean.setType(annotation2.type());
//						webSocketBean.setValue(module);
//						handleWebSocketMethod(webSocketBean, class1, object);
//					}
				}
				if (!object.isEmpty()) {
					forwardBean.setWs(object.toJSONString());
				}
			}
			forwardBean.setValue(value);
			forwardBean.setMd5(Base64.encode(forwardBean.toString().getBytes(Charset.forName("UTF-8"))));
			forwardBean.get().put("server_url", str);
			forwardTask.insert(forwardBean);
		}
	}

//	private void handleWebSocketMethod(WebSocketBean webSocket, Class<?> class_name, JSONArray object) {
//		Method[] methods2 = class_name.getDeclaredMethods();
//		for (Method method : methods2) {
//			System.out.println("handleWebSocketMethod初始化->" + class_name.getName() + "." + method.getName());
//			WebSocketBean webSocketBean = WebSocketBean.newBean(webSocket);
//			if (method.isAnnotationPresent(WebSocketMethodConf.class)) {
//				WebSocketMethodConf annotation = method.getAnnotation(WebSocketMethodConf.class);
//				WebSocketMethodConfBean webSocketMethodConfBean = new WebSocketMethodConfBean(annotation);
//				webSocketBean.setConf(webSocketMethodConfBean);
//			}
//			webSocketBean.setValue(webSocket.getValue().replace(".*", "." + method.getName()));
//			object.add(webSocketBean.toJson());
//		}
//	}

	private void loadByClass(Class<?> name) {
		for (Class<?> class_name : DataSave.initClassList(name)) {
			if (class_name.isAnnotationPresent(Forward.class)) {
				Forward filter = class_name.getAnnotation(Forward.class);
				if (StringUtils.isNotBlank(filter.url()))
					for (String key : filter.value()) {
						handleKey(key, filter);
					}
				// 向其他服务器发送注入请求消息
				injectOtherServer(filter);
			}
		}
	}

	private void handleKey(String key, Forward filter) {
		String keys[] = key.split("[.]");
		HashMap<String, Object> tempmap = map;
		for (String temp : keys) {
			temp = temp.trim();
			HashMap<String, Object> t = null;
			if ((t = (HashMap<String, Object>) tempmap.get(temp)) == null) {
				t = new HashMap<>();
				tempmap.put(temp, t);
			}
			tempmap = t;
		}
		tempmap.put("&&", filter);

	}

	@Override
	public boolean clear() {
		if (map != null)
			map.clear();
		return true;
	}

	@Override
	public boolean is(String name) {
		if (map == null) {
			throw new NullPointerException("please run init");
		}
		return !map.isEmpty() && map.get(name) != null;
	}

	@Override
	public Object del(String name) {
		if (map == null) {
			throw new NullPointerException("please run init");
		}
		return map.remove(name);
	}

	@Override
	public Object get(String name) {
		if (map == null) {
			throw new NullPointerException("please run init");
		}
		HashMap<String, Object> tempmap = map;
		for (String key : name.split("[.]")) {// TODO 如无意外，暂不用修改
			HashMap<String, Object> temp = (HashMap<String, Object>) tempmap.get(key);
			if (temp == null) {
				temp = (HashMap<String, Object>) tempmap.get("*");
			}
			if (temp == null) {
				return null;
			}
			tempmap = temp;
			if (tempmap.size() == 1 && temp.containsKey("&&")) {
				break;
			}
		}
		return tempmap.get("&&");
	}

	@Override
	public boolean add(String name, Object object) {
		if (map == null) {
			throw new NullPointerException("please run init");
		}
		ForwardBean forwardBean = ForwardBean.newBean(ForwardBean.class, object);
		Forward forward = new Forward() {
			String u = forwardBean.getUrl();
			String v = forwardBean.getValue();

			@Override
			public Class<? extends Annotation> annotationType() {
				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public String[] value() {
				return v.split(",");
			}

			@Override
			public String url() {
				return u;
			}

			@Override
			public String[] inject() {
				return null;
			}

			@Override
			public Class<Mugui>[] classes() {
				// TODO Auto-generated method stub
				return null;
			}

		};
		for (String key : forward.value()) {
			handleKey(key, forward);
		}
		return true;
	}

	@Override
	public boolean isInit() {
		// TODO Auto-generated method stub
		return false;
	}

}
